package com.ruoyi.pos.domain.transaction;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * POS销售主表实体类
 * 
 * 用于记录POS系统中的所有销售信息，包括销售、退货、撤销等操作
 * 支持多种支付方式的混合支付，完整的销售状态管理和数据同步
 * 
 * @author POS System
 * @since 1.0.0
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class PosSale extends BaseEntity {
    
    private static final long serialVersionUID = 1L;

    /**
     * 销售ID（主键）
     */
    private Long transactionId;

    /**
     * 销售流水号
     * 
     * 全局唯一，用于标识一笔完整的销售交易
     */
    @Excel(name = "销售流水号")
    @NotBlank(message = "销售流水号不能为空")
    @Size(max = 32, message = "销售流水号长度不能超过32个字符")
    private String transactionNo;

    /**
     * 本地销售号
     * 
     * Android设备本地生成的销售号，用于离线交易
     */
    @Excel(name = "本地销售号")
    @Size(max = 32, message = "本地销售号长度不能超过32个字符")
    private String localTransactionNo;

    /**
     * 设备ID
     * 
     * 关联pos_device表
     */
    @Excel(name = "设备ID")
    private Long deviceId;

    /**
     * 柜组ID
     * 
     * 关联pos_counter_group表
     */
    @Excel(name = "柜组ID")
    private Long groupId;

    /**
     * 操作员ID
     * 
     * 关联sys_user表
     */
    @Excel(name = "操作员ID")
    private Long userId;

    /**
     * 收银员姓名
     */
    @Excel(name = "收银员姓名")
    @Size(max = 50, message = "收银员姓名长度不能超过50个字符")
    private String cashierName;

    /**
     * 会员ID
     * 
     * 关联第三方会员系统
     */
    @Excel(name = "会员ID")
    private Long memberId;

    /**
     * 会员号
     */
    @Excel(name = "会员号")
    @Size(max = 50, message = "会员号长度不能超过50个字符")
    private String memberNo;

    /**
     * 会员姓名
     */
    @Excel(name = "会员姓名")
    @Size(max = 50, message = "会员姓名长度不能超过50个字符")
    private String memberName;

    /**
     * 销售类型
     * 
     * 1-销售 2-退货 3-换货
     */
    @Excel(name = "销售类型", readConverterExp = "1=销售,2=退货,3=换货")
    @Size(max = 1, message = "销售类型长度不能超过1个字符")
    private String transactionType;

    /**
     * 原销售ID
     * 
     * 退货时使用，关联原销售记录
     */
    @Excel(name = "原销售ID")
    private Long originalTransactionId;

    /**
     * 销售总金额
     */
    @Excel(name = "销售总金额")
    @NotNull(message = "销售总金额不能为空")
    @DecimalMin(value = "0.00", message = "销售总金额不能小于0")
    private BigDecimal totalAmount;

    /**
     * 折扣金额
     */
    @Excel(name = "折扣金额")
    @DecimalMin(value = "0.00", message = "折扣金额不能小于0")
    private BigDecimal discountAmount;

    /**
     * 实付金额
     */
    @Excel(name = "实付金额")
    @NotNull(message = "实付金额不能为空")
    @DecimalMin(value = "0.00", message = "实付金额不能小于0")
    private BigDecimal payAmount;

    /**
     * 找零金额
     */
    @Excel(name = "找零金额")
    @DecimalMin(value = "0.00", message = "找零金额不能小于0")
    private BigDecimal changeAmount;

    /**
     * 获得积分
     */
    @Excel(name = "获得积分")
    @Min(value = 0, message = "获得积分不能小于0")
    private Integer pointsEarned;

    /**
     * 使用积分
     */
    @Excel(name = "使用积分")
    @Min(value = 0, message = "使用积分不能小于0")
    private Integer pointsUsed;

    /**
     * 积分抵扣金额
     */
    @Excel(name = "积分抵扣金额")
    @DecimalMin(value = "0.00", message = "积分抵扣金额不能小于0")
    private BigDecimal pointsAmount;

    /**
     * 商品件数
     */
    @Excel(name = "商品件数")
    @Min(value = 0, message = "商品件数不能小于0")
    private Integer itemCount;

    /**
     * 销售状态
     * 
     * 1-成功 2-失败 3-撤销 4-退货
     */
    @Excel(name = "销售状态", readConverterExp = "1=成功,2=失败,3=撤销,4=退货")
    @Size(max = 1, message = "销售状态长度不能超过1个字符")
    private String transactionStatus;

    /**
     * 支付状态
     * 
     * 1-已支付 2-未支付 3-部分支付 4-退款
     */
    @Excel(name = "支付状态", readConverterExp = "1=已支付,2=未支付,3=部分支付,4=退款")
    @Size(max = 1, message = "支付状态长度不能超过1个字符")
    private String paymentStatus;

    /**
     * 同步状态
     * 
     * 0-未同步 1-已同步 2-同步失败
     */
    @Excel(name = "同步状态", readConverterExp = "0=未同步,1=已同步,2=同步失败")
    @Size(max = 1, message = "同步状态长度不能超过1个字符")
    private String syncStatus;

    /**
     * 销售时间
     */
    @Excel(name = "销售时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @NotNull(message = "销售时间不能为空")
    private Date transactionTime;

    /**
     * 同步时间
     */
    @Excel(name = "同步时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date syncTime;

    /**
     * 小票号
     */
    @Excel(name = "小票号")
    @Size(max = 32, message = "小票号长度不能超过32个字符")
    private String receiptNo;

    /**
     * 打印次数
     */
    @Excel(name = "打印次数")
    @Min(value = 0, message = "打印次数不能小于0")
    private Integer printCount;

    /**
     * 退货原因
     */
    @Excel(name = "退货原因")
    @Size(max = 200, message = "退货原因长度不能超过200个字符")
    private String refundReason;

    /**
     * 备注
     */
    @Excel(name = "备注")
    @Size(max = 500, message = "备注长度不能超过500个字符")
    private String remark;

    // ==================== 扩展字段 ====================

    /**
     * 设备名称（非数据库字段）
     */
    @Excel(name = "设备名称")
    private String deviceName;

    /**
     * 设备编号（非数据库字段）
     */
    @Excel(name = "设备编号")
    private String deviceCode;

    /**
     * 柜组名称（非数据库字段）
     */
    @Excel(name = "柜组名称")
    private String groupName;

    /**
     * 柜组编码（非数据库字段）
     */
    @Excel(name = "柜组编码")
    private String groupCode;

    /**
     * 销售状态显示名称（非数据库字段）
     */
    @Excel(name = "销售状态")
    private String statusDisplay;

    /**
     * 支付状态显示名称（非数据库字段）
     */
    @Excel(name = "支付状态")
    private String paymentStatusDisplay;

    /**
     * 同步状态显示名称（非数据库字段）
     */
    @Excel(name = "同步状态")
    private String syncStatusDisplay;

    /**
     * 销售明细列表（非数据库字段）
     */
    private List<PosSaleDetail> saleDetails;

    /**
     * 支付记录列表（非数据库字段）
     */
    private List<PosSalePay> salePays;

    // ==================== 业务方法 ====================

    /**
     * 获取销售状态显示名称
     */
    public String getStatusDisplay() {
        if (transactionStatus == null) {
            return "未知";
        }
        switch (transactionStatus) {
            case "1": return "成功";
            case "2": return "失败";
            case "3": return "撤销";
            case "4": return "退货";
            default: return "未知";
        }
    }

    /**
     * 获取支付状态显示名称
     */
    public String getPaymentStatusDisplay() {
        if (paymentStatus == null) {
            return "未知";
        }
        switch (paymentStatus) {
            case "1": return "已支付";
            case "2": return "未支付";
            case "3": return "部分支付";
            case "4": return "退款";
            default: return "未知";
        }
    }

    /**
     * 获取同步状态显示名称
     */
    public String getSyncStatusDisplay() {
        if (syncStatus == null) {
            return "未知";
        }
        switch (syncStatus) {
            case "0": return "未同步";
            case "1": return "已同步";
            case "2": return "同步失败";
            default: return "未知";
        }
    }

    /**
     * 判断是否为成功销售
     */
    public boolean isSuccess() {
        return "1".equals(transactionStatus);
    }

    /**
     * 判断是否为退货
     */
    public boolean isRefund() {
        return "4".equals(transactionStatus);
    }

    /**
     * 判断是否已支付
     */
    public boolean isPaid() {
        return "1".equals(paymentStatus);
    }

    /**
     * 判断是否已同步
     */
    public boolean isSynced() {
        return "1".equals(syncStatus);
    }

    /**
     * 计算净销售金额
     * 
     * @return 净销售金额 = 总金额 - 折扣金额
     */
    public BigDecimal getNetAmount() {
        if (totalAmount == null) {
            return BigDecimal.ZERO;
        }
        BigDecimal discount = discountAmount != null ? discountAmount : BigDecimal.ZERO;
        return totalAmount.subtract(discount);
    }

    /**
     * 计算折扣率
     * 
     * @return 折扣率百分比
     */
    public BigDecimal getDiscountRate() {
        if (totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal discount = discountAmount != null ? discountAmount : BigDecimal.ZERO;
        return discount.divide(totalAmount, 4, BigDecimal.ROUND_HALF_UP)
                       .multiply(BigDecimal.valueOf(100));
    }

    /**
     * 获取销售摘要信息
     * 
     * @return 销售摘要
     */
    public String getSummary() {
        StringBuilder summary = new StringBuilder();
        summary.append("销售号: ").append(transactionNo);
        summary.append(", 金额: ¥").append(totalAmount != null ? 
            totalAmount.setScale(2, BigDecimal.ROUND_HALF_UP) : "0.00");
        summary.append(", 状态: ").append(getStatusDisplay());
        summary.append(", 时间: ").append(transactionTime != null ? 
            new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(transactionTime) : "未知");
        
        return summary.toString();
    }

    /**
     * 验证销售数据完整性
     * 
     * @return 是否完整
     */
    public boolean isDataComplete() {
        return transactionNo != null && !transactionNo.trim().isEmpty() &&
               totalAmount != null && totalAmount.compareTo(BigDecimal.ZERO) > 0 &&
               payAmount != null && payAmount.compareTo(BigDecimal.ZERO) > 0 &&
               transactionTime != null;
    }

    // ==================== 备用扩展字段 ====================
    
    /**
     * 备用字段1
     */
    private String reserved1;

    /**
     * 备用字段2
     */
    private String reserved2;

    /**
     * 备用字段3
     */
    private String reserved3;

    /**
     * 备用字段4
     */
    private String reserved4;

    /**
     * 备用字段5
     */
    private String reserved5;
}
